<template>
  <div class="search-form" :class="[`search-form--${layout}`, { 'search-form--collapsed': collapsed }]">
    <el-form
      ref="formRef"
      :model="formData"
      :label-width="labelWidth"
      :size="size"
      :inline="layout === 'inline'"
      class="search-form__form"
    >
      <template v-for="(field, index) in visibleFields" :key="field.prop">
        <el-form-item
          :label="field.label"
          :prop="field.prop"
          :class="[
            'search-form__item',
            { 'search-form__item--hidden': index >= maxVisibleItems && collapsed }
          ]"
        >
          <!-- 输入框 -->
          <el-input
            v-if="field.type === 'input'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            :clearable="field.clearable !== false"
            v-bind="field.props"
          />
          
          <!-- 选择器 -->
          <el-select
            v-else-if="field.type === 'select'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :clearable="field.clearable !== false"
            v-bind="field.props"
          >
            <el-option
              v-for="option in field.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
              :disabled="option.disabled"
            />
          </el-select>
          
          <!-- 日期选择器 -->
          <el-date-picker
            v-else-if="field.type === 'date'"
            v-model="formData[field.prop]"
            :type="field.dateType || 'date'"
            :placeholder="field.placeholder || `请选择${field.label}`"
            :clearable="field.clearable !== false"
            v-bind="field.props"
          />
          
          <!-- 日期范围选择器 -->
          <el-date-picker
            v-else-if="field.type === 'daterange'"
            v-model="formData[field.prop]"
            type="daterange"
            :start-placeholder="field.startPlaceholder || '开始日期'"
            :end-placeholder="field.endPlaceholder || '结束日期'"
            :clearable="field.clearable !== false"
            v-bind="field.props"
          />
          
          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="field.type === 'number'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder || `请输入${field.label}`"
            v-bind="field.props"
          />
          
          <!-- 自定义插槽 -->
          <slot
            v-else-if="field.type === 'slot'"
            :name="field.slotName || field.prop"
            :field="field"
            :value="formData[field.prop]"
            :setValue="(val: any) => formData[field.prop] = val"
          />
        </el-form-item>
      </template>
      
      <!-- 操作按钮 -->
      <el-form-item class="search-form__actions">
        <el-button type="primary" :loading="searching" @click="handleSearch">
          <el-icon><Search /></el-icon>
          {{ searchText }}
        </el-button>
        <el-button @click="handleReset">
          <el-icon><Refresh /></el-icon>
          {{ resetText }}
        </el-button>
        
        <!-- 展开/收起按钮 -->
        <el-button
          v-if="showCollapseButton"
          text
          type="primary"
          @click="toggleCollapsed"
        >
          {{ collapsed ? expandText : collapseText }}
          <el-icon class="collapse-icon" :class="{ 'is-expanded': !collapsed }">
            <ArrowDown />
          </el-icon>
        </el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue'
import { Search, Refresh, ArrowDown } from '@element-plus/icons-vue'
import type { FormInstance } from 'element-plus'

export interface SearchFieldOption {
  label: string
  value: any
  disabled?: boolean
}

export interface SearchField {
  // 字段属性
  prop: string
  label: string
  type: 'input' | 'select' | 'date' | 'daterange' | 'number' | 'slot'
  
  // 通用属性
  placeholder?: string
  clearable?: boolean
  defaultValue?: any
  
  // 选择器专用
  options?: SearchFieldOption[]
  
  // 日期选择器专用
  dateType?: 'date' | 'datetime' | 'year' | 'month' | 'week'
  startPlaceholder?: string
  endPlaceholder?: string
  
  // 自定义属性
  props?: Record<string, any>
  
  // 插槽名称（type为slot时使用）
  slotName?: string
}

export interface SearchFormProps {
  // 字段配置
  fields: SearchField[]
  // 布局方式
  layout?: 'inline' | 'grid' | 'vertical'
  // 表单尺寸
  size?: 'large' | 'default' | 'small'
  // 标签宽度
  labelWidth?: string | number
  // 默认值
  defaultValues?: Record<string, any>
  // 最大可见项数（超出时显示展开按钮）
  maxVisibleItems?: number
  // 是否正在搜索
  searching?: boolean
  // 按钮文本
  searchText?: string
  resetText?: string
  expandText?: string
  collapseText?: string
  // 是否自动搜索（值变化时）
  autoSearch?: boolean
  // 防抖延迟（毫秒）
  debounce?: number
}

const props = withDefaults(defineProps<SearchFormProps>(), {
  layout: 'inline',
  size: 'default',
  labelWidth: 'auto',
  maxVisibleItems: 3,
  searching: false,
  searchText: '搜索',
  resetText: '重置',
  expandText: '展开',
  collapseText: '收起',
  autoSearch: false,
  debounce: 300
})

const emit = defineEmits<{
  search: [values: Record<string, any>]
  reset: []
  change: [prop: string, value: any, values: Record<string, any>]
}>()

const formRef = ref<FormInstance>()
const collapsed = ref(true)

// 初始化表单数据
const initFormData = () => {
  const data: Record<string, any> = {}
  
  props.fields.forEach(field => {
    if (props.defaultValues && props.defaultValues[field.prop] !== undefined) {
      data[field.prop] = props.defaultValues[field.prop]
    } else if (field.defaultValue !== undefined) {
      data[field.prop] = field.defaultValue
    } else {
      data[field.prop] = null
    }
  })
  
  return data
}

const formData = reactive(initFormData())

// 可见字段
const visibleFields = computed(() => props.fields)

// 是否显示展开按钮
const showCollapseButton = computed(() => {
  return props.fields.length > props.maxVisibleItems
})

// 搜索处理
const handleSearch = () => {
  const values = { ...formData }
  // 清理空值
  Object.keys(values).forEach(key => {
    if (values[key] === null || values[key] === '' || values[key] === undefined) {
      delete values[key]
    }
  })
  emit('search', values)
}

// 重置处理
const handleReset = () => {
  formRef.value?.resetFields()
  
  // 重置为初始值
  props.fields.forEach(field => {
    if (props.defaultValues && props.defaultValues[field.prop] !== undefined) {
      formData[field.prop] = props.defaultValues[field.prop]
    } else if (field.defaultValue !== undefined) {
      formData[field.prop] = field.defaultValue
    } else {
      formData[field.prop] = null
    }
  })
  
  emit('reset')
  
  // 重置后自动搜索
  if (props.autoSearch) {
    handleSearch()
  }
}

// 切换展开状态
const toggleCollapsed = () => {
  collapsed.value = !collapsed.value
}

// 自动搜索
let searchTimer: NodeJS.Timeout | null = null

const autoSearchHandler = () => {
  if (!props.autoSearch) return
  
  if (searchTimer) {
    clearTimeout(searchTimer)
  }
  
  searchTimer = setTimeout(() => {
    handleSearch()
  }, props.debounce)
}

// 监听表单数据变化
watch(
  formData,
  (newValues, oldValues) => {
    // 发出change事件
    for (const prop in newValues) {
      if (newValues[prop] !== oldValues?.[prop]) {
        emit('change', prop, newValues[prop], newValues)
        break
      }
    }
    
    // 自动搜索
    autoSearchHandler()
  },
  { deep: true }
)

// 重新初始化默认值
watch(() => props.defaultValues, (newDefaults) => {
  if (newDefaults) {
    Object.assign(formData, newDefaults)
  }
}, { deep: true })

// 暴露方法
defineExpose({
  search: handleSearch,
  reset: handleReset,
  getValues: () => ({ ...formData }),
  setValues: (values: Record<string, any>) => Object.assign(formData, values),
  clearValues: () => handleReset()
})
</script>

<style scoped>
.search-form {
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  margin-bottom: 16px;
}

.search-form__form {
  width: 100%;
}

/* 内联布局 */
.search-form--inline .search-form__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
}

.search-form--inline .search-form__item {
  margin-bottom: 0;
  flex-shrink: 0;
}

.search-form--inline .search-form__actions {
  margin-bottom: 0;
  margin-left: auto;
}

/* 网格布局 */
.search-form--grid .search-form__form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
  align-items: end;
}

.search-form--grid .search-form__actions {
  grid-column: -1;
  justify-self: end;
}

/* 垂直布局 */
.search-form--vertical .search-form__item {
  margin-bottom: 16px;
}

/* 折叠状态 */
.search-form--collapsed .search-form__item--hidden {
  display: none !important;
}

/* 操作区域 */
.search-form__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.search-form__actions .el-button {
  margin: 0;
}

/* 展开/收起图标 */
.collapse-icon {
  margin-left: 4px;
  transition: transform 0.3s;
}

.collapse-icon.is-expanded {
  transform: rotate(180deg);
}

/* 响应式设计 */
@media (max-width: 768px) {
  .search-form {
    padding: 16px;
  }
  
  .search-form--inline {
    display: block;
  }
  
  .search-form--inline .search-form__form {
    flex-direction: column;
    align-items: stretch;
  }
  
  .search-form--inline .search-form__item {
    width: 100%;
    margin-bottom: 16px;
  }
  
  .search-form--inline .search-form__actions {
    margin-left: 0;
    justify-content: center;
  }
  
  .search-form--grid .search-form__form {
    grid-template-columns: 1fr;
  }
  
  .search-form__actions {
    flex-direction: column;
    width: 100%;
  }
  
  .search-form__actions .el-button {
    width: 100%;
  }
}
</style>
